import fs from "fs";
import { promisify } from "util";
import { join } from "path";
import lodash from "lodash";
import {
  Follow,
  User,
  Video,
  VideoCollect,
  VideoLike,
} from "../models/index.js";
import { success, successResponse, errorResponse } from "../utils/result.js";
import { signToken } from "../utils/jwt.js";
import mongoose from "mongoose";
const rename = promisify(fs.rename);

// 检查用户是否存在
const checkUserExists = async (uId) => {
  return await User.findById(uId);
};
// 验证uId是否有效
const checkuIdValid = (uId) => {
  if (!mongoose.Types.ObjectId.isValid(uId)) {
    throw new Error("输入的ID不是ObjectId格式");
  }
};
/**
 * 用户注册
 */
export const register = async (req, res, next) => {
  const userModel = new User(req.body);
  try {
    await userModel.save();
    res.status(201).json(success("注册成功"));
  } catch (err) {
    next(err);
  }
};
/**
 * 用户登录
 */
export const login = async (req, res, next) => {
  const userModel = new User(req.body);
  try {
    const user = await User.findOne({ phone: userModel.phone });
    if (!user) {
      res.status(404).json(errorResponse("用户不存在"));
    } else if (user.password !== userModel.password) {
      res.status(403).json(errorResponse("密码错误"));
    }
    const token = signToken(user);
    res.status(200).json(successResponse(token));
  } catch (err) {
    next(err);
  }
};
// 获取当前用户信息
export const my = async (req, res, next) => {
  try {
    const user = await User.findById(req.user.id);
    // 去除密码
    const { password, ...userInfo } = user._doc;
    res.status(200).json(successResponse(userInfo));
  } catch (err) {
    next(err);
  }
};
/**
 * 用户信息更新
 */
export const update = async (req, res, next) => {
  try {
    await User.findByIdAndUpdate(req.user.id, req.body, {
      new: true,
    });
    res.status(200).json(success("更新成功"));
  } catch (err) {
    next(err);
  }
};
/**
 * 用户头像更新
 */
export const avatar = async (req, res, next) => {
  let fileArr = req.file.originalname.split(".");
  let fileType = fileArr[fileArr.length - 1];
  const oldPath = join(
    __dirname,
    "../public/uploads/avatar",
    req.file.filename
  );
  const newPath = join(
    __dirname,
    "../public/uploads/avatar",
    req.file.filename + "." + fileType
  );
  try {
    await rename(oldPath, newPath);
    await User.findByIdAndUpdate(
      req.user.id,
      { avatar: newPath },
      { new: true }
    );
    res.status(200).json(success("更新成功"));
  } catch (err) {
    next(err);
  }
};

/**
 * 用户详情
 */
export const oInfo = async (req, res, next) => {
  const uId = req.params.uId;
  try {
    // 验证 uId 是否为有效的 ObjectId
    checkuIdValid(uId);
    let user = await checkUserExists(uId);
    if (!user) {
      return res.status(404).json(errorResponse("用户不存在"));
    }
    user = lodash.pick(user, [
      "_id",
      "username",
      "avatar",
      "followCount",
      "fansCount",
      "likeCount",
      "cover",
      "description",
    ]);
    // 是否关注
    let isFollow = false;
    if (req.user) {
      const record = await Follow.findOne({
        user: req.user.id,
        follow: uId,
      });
      isFollow = !!record;
    }
    res.status(200).json(
      successResponse({
        user,
        isFollow,
      })
    );
  } catch (err) {
    next(err);
  }
};

/**
 * 获取用户发布的视频列表
 */
export const videos = async (req, res, next) => {
  const uId = req.params.uId;
  const { pageNum = 1, pageSize = 10, keyword } = req.query;
  const skip = (pageNum - 1) * pageSize;
  try {
    checkuIdValid(uId);
    const user = await checkUserExists(uId);
    if (!user) {
      return res.status(404).json(errorResponse("用户不存在"));
    }
    const videos = await Video.find({ user: uId })
      .skip(skip)
      .limit(pageSize)
      .sort({ createdAt: -1 });
    const total = await Video.countDocuments({ user: uId });
    res.status(200).json(successResponse({ videos, total }));
  } catch (err) {
    next(err);
  }
};

/**
 * 关注用户
 */
export const follow = async (req, res, next) => {
  // 当前用户id
  const userId = req.user.id;
  // 关注的用户id
  const followId = req.params.uId;
  try {
    checkuIdValid(followId);
    const user = await checkUserExists(followId);
    if (!user) {
      return res.status(404).json(errorResponse("用户不存在"));
    }
    if (userId === followId) {
      return res.status(400).json(errorResponse("不能关注自己"));
    }
    const record = await Follow.findOne({
      user: userId,
      follow: followId,
    });
    if (!record) {
      await Promise.all([
        // 关注
        new Follow({
          user: userId,
          follow: followId,
        }).save(),
        // 更新用户关注数和粉丝数
        User.findByIdAndUpdate(
          userId,
          { $inc: { followCount: 1 } },
          { new: true }
        ),
        User.findByIdAndUpdate(
          followId,
          { $inc: { fansCount: 1 } },
          { new: true }
        ),
      ]);
      res.status(200).json(success("关注成功"));
    } else {
      res.status(400).json(errorResponse("当前用户已关注"));
    }
  } catch (err) {
    next(err);
  }
};

/**
 * 取消关注
 */
export const unfollow = async (req, res, next) => {
  // 当前用户id
  const userId = req.user.id;
  // 关注的用户id
  const followId = req.params.uId;
  try {
    checkuIdValid(followId);
    const user = await checkUserExists(followId);
    if (!user) {
      return res.status(404).json(errorResponse("用户不存在"));
    }
    if (userId === followId) {
      return res.status(400).json(errorResponse("不能取消关注自己"));
    }
    const record = await Follow.findOne({
      user: userId,
      follow: followId,
    });
    if (record) {
      await Follow.findByIdAndDelete(record._id);
      await Promise.all([
        // 更新用户关注数和粉丝数
        User.findByIdAndUpdate(
          userId,
          { $inc: { followCount: -1 } },
          {
            new: true,
          }
        ),
        User.findByIdAndUpdate(
          followId,
          { $inc: { fansCount: -1 } },
          {
            new: true,
          }
        ),
      ]);
      res.status(200).json(success("取消关注成功"));
    } else {
      res.status(400).json(errorResponse("当前用户未关注"));
    }
  } catch (err) {
    next(err);
  }
};

/**
 * 获取关注列表
 */
export const follows = async (req, res, next) => {
  const uId = req.params.uId;
  const { pageNum = 1, pageSize = 10, keyword } = req.query;
  const skip = (pageNum - 1) * pageSize;
  try {
    checkuIdValid(uId);
    const user = await checkUserExists(uId);
    if (!user) {
      return res.status(404).json(errorResponse("用户不存在"));
    }
    let follows = await Follow.find({ user: uId })
      .skip(skip)
      .limit(pageSize)
      .sort({ createTime: -1 })
      .populate("follow");
    // 根据keyword模糊查询
    if (keyword) {
      follows = follows.filter((item) => {
        return item.follow.username.includes(keyword);
      });
    }
    follows = await Promise.all(
      follows.map(async (item) => {
        return {
          ...lodash.pick(item.follow, ["_id", "username", "avatar"]),
        };
      })
    );
    // 获取总数
    const total = await Follow.countDocuments({ user: req.params.uId });
    res.status(200).json(successResponse({ follows, total }));
  } catch (err) {
    next(err);
  }
};

/**
 * 获取粉丝列表
 */
export const fans = async (req, res, next) => {
  const uId = req.params.uId;
  const { pageNum = 1, pageSize = 10 } = req.query;
  const skip = (pageNum - 1) * pageSize;
  try {
    checkuIdValid(uId);
    const user = await checkUserExists(uId);
    if (!user) {
      return res.status(404).json(errorResponse("用户不存在"));
    }
    let fans = await Follow.find({ follow: uId })
      .skip(skip)
      .limit(pageSize)
      .sort({ createTime: -1 })
      .populate("user");
    fans = await Promise.all(
      fans.map(async (item) => {
        // 判断是否互相关注
        let isFollow = false;
        const record = await Follow.findOne({
          user: req.user.uId,
          // 被关注的用户
          follow: item.user._id,
        });
        if (record) {
          isFollow = true;
        }
        return {
          ...lodash.pick(item.user, ["_id", "username", "avatar"]),
          isFollow,
        };
      })
    );
    const total = await Follow.countDocuments({ follow: req.params.uId });
    res.status(200).json(successResponse({ fans, total }));
  } catch (err) {
    next(err);
  }
};

/**
 * 用户点赞视频列表
 */
export const likes = async (req, res, next) => {
  const uId = req.params.uId;
  const { pageNum = 1, pageSize = 10 } = req.query;
  const skip = (pageNum - 1) * pageSize;
  try {
    checkuIdValid(uId);
    const user = await checkUserExists(uId);
    if (!user) {
      return res.status(404).json(errorResponse("用户不存在"));
    }
    let likes = await VideoLike.find({ user: uId })
      .skip(skip)
      .limit(pageSize)
      .sort({ createTime: -1 })
      .populate("video");
    likes = likes.map((item) => {
      return {
        ...lodash.pick(item.video, ["_id", "title", "cover", "likeCount"]),
      };
    });
    const total = await VideoLike.countDocuments({ user: uId });
    res.status(200).json(successResponse({ likes, total }));
  } catch (err) {
    next();
  }
};

/**
 * 获取收藏视列表
 */
export const collects = async (req, res, next) => {
  const uId = req.params.uId;
  const { pageNum = 1, pageSize = 10 } = req.query;
  const skip = (pageNum - 1) * pageSize;
  try {
    checkuIdValid(uId);
    const user = await checkUserExists(uId);
    if (!user) {
      return res.status(404).json(errorResponse("用户不存在"));
    }
    let collects = await VideoCollect.find({ user: uId })
      .skip(skip)
      .limit(pageSize)
      .sort({ createTime: -1 })
      .populate("video");
    collects = collects.map((item) => {
      return {
        ...lodash.pick(item.video, ["_id", "title", "cover", "likeCount"]),
      };
    });
    const total = await VideoCollect.countDocuments({ user: uId });
    res.status(200).json(successResponse({ collects, total }));
  } catch (err) {
    next(err);
  }
};
